package org.ling.xuan.action;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.task.ProjectTaskManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.concurrency.Promise;
import org.ling.xuan.dao.ProjectDao;
import org.ling.xuan.entity.mo.ProjectSetting;
import org.ling.xuan.util.LoggerUtil;
import org.ling.xuan.util.LxOptional;
import org.ling.xuan.util.LxStrUtil;

import java.nio.charset.StandardCharsets;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;


/**
 * lx添加项目操作
 *
 * @author liting50684
 * @date 2023/08/01
 */
public class LxReDeploy extends AnAction {
    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        String filePath = LxOptional.of(e, c -> c.getDataContext().getData(CommonDataKeys.VIRTUAL_FILE).getPath()).orElse("");
        String basePath = LxOptional.of(e, c -> c.getProject().getBasePath()).orElse("");
        ProjectSetting projectSetting = ProjectDao.getSetting(basePath);
        if (projectSetting == null) {
            return;
        }
        if (StrUtil.isNotBlank(projectSetting.getBuildPath()) && filePath.startsWith(projectSetting.getWebPath())) {
            //WebResource文件直接复制到对应目录
            if (StrUtil.isNotBlank(projectSetting.getBuildPath())) {
                String buildFilePath = filePath.replace(projectSetting.getWebPath(), projectSetting.getBuildPath());
                LoggerUtil.log(e.getProject(), "build file path:{}", buildFilePath);
                FileUtil.mkParentDirs(buildFilePath);
                FileUtil.copyFile(filePath, buildFilePath, StandardCopyOption.REPLACE_EXISTING);
            }
            if (StrUtil.isNotBlank(projectSetting.getCompilePath())) {
                String compileFilePath = filePath.replace(projectSetting.getWebPath(), projectSetting.getCompilePath());
                LoggerUtil.log(e.getProject(), "compile file path:{}", compileFilePath);
                FileUtil.mkParentDirs(compileFilePath);
                FileUtil.copyFile(filePath, compileFilePath, StandardCopyOption.REPLACE_EXISTING);
            }
        } else {
            List<String> sourceRoot = getSourceRoot(e.getProject(), false);
            String matchSource = LxStrUtil.startWithLeastOne(filePath, sourceRoot);
            //如果是项目资源文件
            if (StrUtil.isNotBlank(matchSource)) {
                LoggerUtil.log(e.getProject(),"该文件所在资源目录:"+matchSource);
                if (filePath.endsWith(".java")) {
                    List<String> ss = FileUtil.readLines(filePath, StandardCharsets.UTF_8);
                    String pkg = getPackageFormJava(ss);
                    String appendPath = pkg.replace(".", "/") + "/";
                    String className = FileUtil.getPrefix(filePath) + ".class";
                    if (StrUtil.isNotBlank(projectSetting.getCompilePath())) {
                        String classFileCompilePath = projectSetting.getCompilePath() + "/" + appendPath + className;
                        LoggerUtil.log(e.getProject(), "compile file path:{}", classFileCompilePath);
                        VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl("file://" + filePath);
                        Promise<ProjectTaskManager.Result> resultPromise = ProjectTaskManager.getInstance(e.getProject()).compile(virtualFile);
                        resultPromise.onProcessed(r -> {
                            LoggerUtil.log(e.getProject(), "compiler success:{}>>>{}", filePath, classFileCompilePath);
                            if (StrUtil.isNotBlank(projectSetting.getBuildPath())) {
                                if(!FileUtil.exist(classFileCompilePath)){
                                    try {
                                        Thread.sleep(1000);
                                    } catch (InterruptedException ex) {
                                        ex.printStackTrace();
                                    }
                                }
                                if(FileUtil.exist(classFileCompilePath)) {
                                    String buildFilePath = projectSetting.getBuildPath() + "/WEB-INF/classes/" + appendPath + className;
                                    LoggerUtil.log(e.getProject(), "build file path:{}", buildFilePath);
                                    FileUtil.mkParentDirs(buildFilePath);
                                    FileUtil.copyFile(classFileCompilePath, buildFilePath, StandardCopyOption.REPLACE_EXISTING);
                                    LoggerUtil.log(e.getProject(), "to build path success:{}>>>{}", classFileCompilePath, buildFilePath);
                                }else{
                                    LoggerUtil.log(e.getProject(),"!!! warn !!! compile file not exists");
                                }
                            }
                        });

                    }
                } else {
                    //非Java文件处理
                    if (StrUtil.isNotBlank(projectSetting.getBuildPath())) {
                        LoggerUtil.log(e.getProject(),"replace prefix:{}>>>{}",matchSource,projectSetting.getBuildPath() + "/WEB-INF/classes");
                        String buildFilePath = filePath.replace(matchSource, projectSetting.getBuildPath() + "/WEB-INF/classes");
                        LoggerUtil.log(e.getProject(), "build file path:{}", buildFilePath);
                        FileUtil.mkParentDirs(buildFilePath);
                        FileUtil.copyFile(filePath, buildFilePath, StandardCopyOption.REPLACE_EXISTING);
                    }
                    LoggerUtil.log(e.getProject(),"replace prefix:{}>>>{}",matchSource,projectSetting.getCompilePath() + "/WEB-INF/classes");
                    String compileFilePath = filePath.replace(matchSource, projectSetting.getCompilePath());
                    LoggerUtil.log(e.getProject(), "compile file path:{}", compileFilePath);
                    FileUtil.mkParentDirs(compileFilePath);
                    FileUtil.copyFile(filePath, compileFilePath, StandardCopyOption.REPLACE_EXISTING);
                }
            } else {
                List<String> testRoots = getSourceRoot(e.getProject(), true);
                String ms = LxStrUtil.startWithLeastOne(filePath, testRoots);
                if (StrUtil.isNotBlank(ms)) {
                    LoggerUtil.log(e.getProject(),"该文件所在测试资源目录:"+matchSource);
                    if (filePath.endsWith(".java")) {
                        VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl("file://" + filePath);
                        Promise<ProjectTaskManager.Result> resultPromise = ProjectTaskManager.getInstance(e.getProject()).compile(virtualFile);
                        resultPromise.onProcessed(r -> {
                            String compileFilePath = filePath.replace(ms, projectSetting.getTestCompilePath());
                            LoggerUtil.log(e.getProject(), "test compile file path:{}", compileFilePath.replace(".java",".class"));
                        });
                    } else {
                        String compileFilePath = filePath.replace(ms, projectSetting.getTestCompilePath());
                        LoggerUtil.log(e.getProject(), "test compile file path:{}", compileFilePath);
                        FileUtil.mkParentDirs(compileFilePath);
                        FileUtil.copyFile(filePath, compileFilePath, StandardCopyOption.REPLACE_EXISTING);
                    }
                } else {
                    LoggerUtil.log(e.getProject(), "非资源目录:{}", filePath);
                }
            }
        }
    }

    private String getPackageFormJava(List<String> ss) {
        for (String s : ss) {
            s = s.trim();
            if (s.startsWith("package") && s.endsWith(";")) {
                return s.substring("package".length(), s.length() - 1).trim();
            }
        }
        return "";
    }

    private List<String> getSourceRoot(Project project, boolean testSource) {
        List<String> roots = new ArrayList<>();
        ModuleManager moduleManager = ModuleManager.getInstance(project);
        Module[] modules = moduleManager.getModules();
        for (int i = 0; i < modules.length; i++) {
            ModuleRootManager rootManager = ModuleRootManager.getInstance(modules[i]);
            VirtualFile[] files = null;
            if(!testSource){
                files=rootManager.getSourceRoots(false);
                for (VirtualFile f : files) {
                    roots.add(LxStrUtil.unionPath(f.getPath()));
                }
            }else{
                List<String> r1 = new ArrayList<>();
                files=rootManager.getSourceRoots(false);
                for (VirtualFile f : files) {
                    r1.add(LxStrUtil.unionPath(f.getPath()));
                }
                List<String> r2 = new ArrayList<>();
                files=rootManager.getSourceRoots(true);
                for (VirtualFile f : files) {
                    r2.add(LxStrUtil.unionPath(f.getPath()));
                }
                roots= new ArrayList<>(CollUtil.subtract(r2, r1));
            }
           
        }
        //按路径长短  优先匹配长的
        roots.sort(Comparator.comparing(String::length));
        return roots;
    }

    @Override
    public void update(AnActionEvent e) {
        String filePath = LxOptional.of(e, c -> c.getDataContext().getData(CommonDataKeys.VIRTUAL_FILE).getPath()).orElse("");
        e.getPresentation().setEnabledAndVisible(FileUtil.isFile(filePath));
    }
}
